#include "Usuario.h"

Usuario* Usuario::instance = NULL;

Usuario::Usuario() {
	stringstream logstream;
	logstream << "Creando usuario, PID:  \"" << getpid();
	Log::getInstance()->log(logstream.str());
	id = getpid();
	carpetaDescarga  = "";
	archivosCompartidos = new list<string>;
	handler = new PUBLISH_FILES_Handler();
	// se r e g i s t r a el event handler d e c l a r a d o antes
	SignalHandler::getInstance ()->registrarHandler( PUBLISH_FILES_SIGNAL , handler ) ;

	handlerSolicitudDescarga = new UPLOAD_Handler();
	// se r e g i s t r a el event handler d e c l a r a d o antes
	SignalHandler::getInstance ()->registrarHandler( UPLOAD_SIGNAL , handlerSolicitudDescarga ) ;

	exitchild_handler = new EXITCHILD_Handler();
	SignalHandler::getInstance()->registrarHandler ( EXITCHILD_SIGNAL, exitchild_handler );
	stringstream logstream2;
	logstream2 << "Usuario PID: " << getpid() << ", creado";
	Log::getInstance()->log(logstream2.str());
}

Usuario::~Usuario() {
	stringstream logstream;
	logstream << "Destruyendo usuario id: " << this->id;
	Log::getInstance()->log(logstream.str());
	archivosCompartidos->clear();
	delete archivosCompartidos;
	SignalHandler::getInstance ()->removerHandler(PUBLISH_FILES_SIGNAL);
	SignalHandler::getInstance ()->removerHandler(UPLOAD_SIGNAL);
	SignalHandler::getInstance ()->removerHandler(EXITCHILD_SIGNAL);
	delete handler;
	delete handlerSolicitudDescarga;
	delete exitchild_handler;

	descargas.clear();
	subidas.clear();
	stringstream logstream2;
	logstream2 << "Usuario destruido id: " << this->id;
	Log::getInstance()->log(logstream2.str());
}

Usuario* Usuario::getInstance(){
	if (instance == NULL) {
		instance = new Usuario();
	}
	return instance;
}

void Usuario::destroy() {
	if (instance != NULL) {
		delete instance;
		instance = NULL;
	}
}

void Usuario::compartirArchivo(string path)
{
	Log::getInstance()->log("Agregando \""+path+"\" a archivos compartidos.");
	archivosCompartidos->push_back(path);
	archivosCompartidos->unique();
	Log::getInstance()->log("\""+path+"\" agregado a archivos compartidos.");
}

list<string> Usuario::misArchivosCompartidos()
{
	return * archivosCompartidos;
}

string Usuario::mostrarMisArchivosCompartidos(){
	list<string>::iterator itBeg = archivosCompartidos->begin();
	list<string>::iterator itBack = archivosCompartidos->end();
	stringstream sstream;
	for(int i = 1;itBeg != itBack; itBeg++, i++)
		sstream << i << "\t" << *itBeg << endl;
	return sstream.str();
}

void Usuario::dejarDeCompartir(string path){
	archivosCompartidos->remove(path);
}

bool Usuario::exitChild() {
	return exitchild_handler->isChildExit();
}

void Usuario::registrarDescarga(int pid) {
	descargas.push_back(pid);
}

void Usuario::registrarSubida(int pid) {
	subidas.push_back(pid);
}

void Usuario::terminarTransferencias() {
	Log::getInstance()->log("Terminando trasferencias.");
	int status;
	while (!subidas.empty()) {
		stringstream logstream;
		logstream << "Esperando subida PID:" << subidas.back();
		Log::getInstance()->log(logstream.str());
		waitpid(subidas.back(), &status, 0);
		subidas.pop_back();
	}

	while (!descargas.empty()) {
		stringstream logstream;
		logstream << "Esperando descarga PID:" << descargas.back();
		Log::getInstance()->log(logstream.str());
		waitpid(descargas.back(), &status, 0);
		descargas.pop_back();
	}
	Log::getInstance()->log("Transferecias finalizadas.");
}
